package com.jiexin.service;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.jiexin.dao.SysAclMapper;
import com.jiexin.dao.SysAclModuleMapper;
import com.jiexin.dao.SysDeptMapper;
import com.jiexin.dto.AclDto;
import com.jiexin.dto.AclModuleLevelDto;
import com.jiexin.dto.DeptLevelDto;
import com.jiexin.model.SysAcl;
import com.jiexin.model.SysAclModule;
import com.jiexin.model.SysDept;
import com.jiexin.model.SysRole;
import com.jiexin.util.LevelUtil;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.security.acl.Acl;
import java.util.*;
import java.util.stream.Collector;
import java.util.stream.Collectors;

/**
 * @Author: Jay_Liu
 * @Description:
 * @Date: Created in 20:49 2018/4/3 0003
 * @Modified By:
 */
@Service
public class SysTreeService {

    @Resource
    private SysDeptMapper sysDeptMapper;

    @Resource
    private SysAclModuleMapper sysAclModuleMapper;
    
    @Resource
    private SysCoreService sysCoreService;

    @Resource
    private SysAclMapper sysAclMapper;

    /**
     * 用户分配的对应的权限树
     * @param userId
     * @return
     */
    public List<AclModuleLevelDto> userAclTree(Integer userId) {
        List<SysAcl> userAclList = sysCoreService.getUserAclList(userId);
        List<AclDto> aclDtoList = Lists.newArrayList();
        for(SysAcl acl : userAclList) {
            AclDto dto = AclDto.adapt(acl);
            dto.setChecked(true);
            dto.setHasAcl(true);
            aclDtoList.add(dto);
        }
        return aclListToTree(aclDtoList);
    }

    /**
     * 角色相关的权限树
     * @param roleId
     * @return
     */
    public List<AclModuleLevelDto> roleTree(Integer roleId) {
        //1.获取用户已分配的权限点
        List<SysAcl> userAclList = sysCoreService.getCurrentUserAclList();
        //2.获取当前角色的权限点
        List<SysAcl> roleAclList = sysCoreService.getCurrentRoleAclList(roleId);
        //3.所有权限点
        List<SysAcl> allAclList = sysAclMapper.getAllAcl();

        //将userAclList的每个元素的id组合成一个set集合
        Set<Integer> userAclIdSet = userAclList.stream().map(sysAcl -> sysAcl.getId()).collect(Collectors.toSet());
        Set<Integer> allAclIdSet = roleAclList.stream().map(sysAcl -> sysAcl.getId()).collect(Collectors.toSet());

        //List<AclModuleLevelDto> aclModuleLevelDtos = aclModuleTree();
        //所有权限点集合（附加属性：是否有权限，是否默认选中）
        List<AclDto> aclDtoList = Lists.newArrayList();
        for(SysAcl acl : allAclList) {
            AclDto dto = AclDto.adapt(acl);
            //用户拥有角色权限，则拥有分配角色的权限
            if (userAclIdSet.contains(acl.getId())){
                dto.setHasAcl(true);
            }
            //当前角色拥有改权限，则此权限默认选中
            if (allAclIdSet.contains(acl.getId())) {
                dto.setChecked(true);
            }
            aclDtoList.add(dto);
        }
        return aclListToTree(aclDtoList);
    }

    /**
     * 权限模块与权限点搭建成树形结构
     * @param aclDtoList
     * @return
     */
    public List<AclModuleLevelDto> aclListToTree(List<AclDto> aclDtoList) {
        if(CollectionUtils.isEmpty(aclDtoList)) {
            return Lists.newArrayList();
        }
        List<AclModuleLevelDto> aclModuleLevelDtos = aclModuleTree();
        //权限摸块ID->权限点
        Multimap<Integer,AclDto> moduleIdAclMap = ArrayListMultimap.create();
        //遍历
        for (AclDto dto : aclDtoList) {
            //若权限为有效
            if (dto.getStatus() == 1){
                moduleIdAclMap.put(dto.getAclModuleId(), dto);
            }
        }
        //权限模块与权限点绑定成树
        bindsAclsWithOrder(aclModuleLevelDtos, moduleIdAclMap);
        return  aclModuleLevelDtos;
    }

    private void bindsAclsWithOrder(List<AclModuleLevelDto> aclModuleLevelDtos, Multimap<Integer, AclDto> moduleIdAclMap) {
        if(CollectionUtils.isEmpty(aclModuleLevelDtos)){
            return ;
        }
        for (AclModuleLevelDto aclModuleLevelDto : aclModuleLevelDtos){
            List<AclDto> aclDtos = (List<AclDto>)moduleIdAclMap.get(aclModuleLevelDto.getId());
            if(CollectionUtils.isNotEmpty(aclDtos)){
                Collections.sort(aclDtos,aclSeqComparator);
                aclModuleLevelDto.setAclList(aclDtos);
                bindsAclsWithOrder(aclModuleLevelDto.getAclModuleList(),moduleIdAclMap);
            }
        }

    }

    /**
     * 系统中存在的部门树
     * @return
     */
    public List<DeptLevelDto> deptTree(){
        List<SysDept> deptList = sysDeptMapper.getAllDept();

        List<DeptLevelDto> dtoList = Lists.newArrayList();
        for (SysDept dept : deptList) {
            DeptLevelDto dto = DeptLevelDto.adapt(dept);
            dtoList.add(dto);
        }
        return deptListToTree(dtoList);
    }

    /**
     * 转换成树形权限模块Model
     * @return
     */
    public List<AclModuleLevelDto> aclModuleTree() {
        //所有的权限模块
        List<SysAclModule> aclModuleList = sysAclModuleMapper.getAllAclModule();
        List<AclModuleLevelDto> dtoList = Lists.newArrayList();
        //转换成树形Model
        for (SysAclModule  aclModule : aclModuleList) {
            AclModuleLevelDto dto = AclModuleLevelDto.adapt(aclModule);
            dtoList.add(dto);
        }
        return aclModuleListToTree(dtoList);
    }

    /**
     * 设置权限模块树形结构
     * @param aclModuleList 权限模块Model
     * @return 树形结构集合
     */
    public List<AclModuleLevelDto> aclModuleListToTree(List<AclModuleLevelDto> aclModuleList) {

        if (CollectionUtils.isEmpty(aclModuleList)) {
            return Lists.newArrayList();
        }
        //定义Map数据结构：level->[模块1，模块2...]
        Multimap<String,AclModuleLevelDto> levelAclModuleMap = ArrayListMultimap.create();
        //最上级权限模块
        List<AclModuleLevelDto> rootList = Lists.newArrayList();
        for (AclModuleLevelDto dto : aclModuleList) {
            levelAclModuleMap.put(dto.getLevel(), dto);
            //若等级为0，则作为最上层的权限模块结构
            if (LevelUtil.ROOT.equals(dto.getLevel())) {
                rootList.add(dto);
            }
        }
        //最上层权限模块排序
        Collections.sort(rootList,aclModuleSeqComparator);
        //递归生成树形结构
        transformAclModuleTree(rootList, LevelUtil.ROOT, levelAclModuleMap);
        return rootList;
    }


    /**
     * 部门等级->部门树
     * @param deptLevelList
     * @return
     */
    public List<DeptLevelDto> deptListToTree(List<DeptLevelDto> deptLevelList) {

        if (CollectionUtils.isEmpty(deptLevelList)) {
            return Lists.newArrayList();
        }
        //level -> [dept1,dept2,...]
        Multimap<String, DeptLevelDto> levelDeptMap = ArrayListMultimap.create();
        List<DeptLevelDto> rootList = Lists.newArrayList();

        for (DeptLevelDto dto : deptLevelList) {
            //key->value:部门等级->部门树
            levelDeptMap.put(dto.getLevel(), dto);
            //第一层级部门
            if (LevelUtil.ROOT.equals(dto.getLevel())) {
                rootList.add(dto);
            }
        }

        //按照seq从小到大进行排序
        Collections.sort(rootList, new Comparator<DeptLevelDto>() {
            public int compare(DeptLevelDto o1, DeptLevelDto o2) {
                return o1.getSeq() - o2.getSeq();
            }
        });
        //递归生成树
        transformDeptTree(rootList, LevelUtil.ROOT, levelDeptMap);
        return  rootList;

    }

    /**
     * 权限模块递归生成树
     * @param aclModuleLevelList 权限模块树形Model集合
     * @param level 模块等级
     * @param levelAclModuleMap 等级与该等级对应的权限模块树形Model
     */
    public void transformAclModuleTree(List<AclModuleLevelDto> aclModuleLevelList, String level, Multimap<String, AclModuleLevelDto> levelAclModuleMap) {

        for (int i = 0 ;i < aclModuleLevelList.size(); i++) {
            //当前权限模块
            AclModuleLevelDto aclModuleLevelDto = aclModuleLevelList.get(i);
            //下一层模块等级=当前模块等级 与 当前模块ID 拼接后
            String nextLevel = LevelUtil.calculateLevel(level, aclModuleLevelDto.getId());
            //获取下一层级权限模块树形Model
            List<AclModuleLevelDto> tempDeptList = (List<AclModuleLevelDto>) levelAclModuleMap.get(nextLevel);
            if (CollectionUtils.isNotEmpty(tempDeptList)) {
                //下一层权限模块排序
                Collections.sort(tempDeptList, aclModuleSeqComparator);
                //设置当前权限模块下层等级树形结构
                aclModuleLevelDto.setAclModuleList(tempDeptList);
                //递归
                transformAclModuleTree(tempDeptList,nextLevel,levelAclModuleMap);
            }
        }
    }

    /**
     * 递归排序
     * @param deptLevelList
     * @param level
     * @param levelDeptMap
     */
    public void transformDeptTree(List<DeptLevelDto> deptLevelList, String level, Multimap<String, DeptLevelDto> levelDeptMap){

        for (int i = 0 ; i<deptLevelList.size(); i++) {
            //遍历该层的每个元素
            DeptLevelDto deptLevelDto = deptLevelList.get(i);
            //处理当前层级的数据 0.1 /0.2 /0.3
            String nextLevel = LevelUtil.calculateLevel(level, deptLevelDto.getId());
            //处理下一层
            List<DeptLevelDto> tempDeptList = (List<DeptLevelDto>)levelDeptMap.get(nextLevel);
            if (CollectionUtils.isNotEmpty(tempDeptList)) {
                //排序
                Collections.sort(tempDeptList, deptSeqComparator);
                //设置下一层部门
                deptLevelDto.setDeptList(tempDeptList);
                //进入到下一层处理
                transformDeptTree(tempDeptList, nextLevel, levelDeptMap);
            }
        }
    }

    //部门排序：按照seq从小到大排序
    public Comparator<DeptLevelDto> deptSeqComparator = new Comparator<DeptLevelDto>() {
        public int compare(DeptLevelDto o1, DeptLevelDto o2) {
            return o1.getSeq() - o2.getSeq();
        }
    };

    //权限模块排序：按照seq从小到大排序
    public Comparator<AclModuleLevelDto> aclModuleSeqComparator = new Comparator<AclModuleLevelDto>() {
        public int compare(AclModuleLevelDto o1, AclModuleLevelDto o2) {
            return o1.getSeq() - o2.getSeq();
        }
    };

    //权限模块排序：按照seq从小到大排序
    public Comparator<AclDto> aclSeqComparator = new Comparator<AclDto>() {
        public int compare(AclDto o1, AclDto o2) {
            return o1.getSeq() - o2.getSeq();
        }
    };

}
